package com.jiangli.aspect;

import com.alibaba.fastjson.JSON;
import com.jiangli.annotation.Log;
import com.jiangli.context.BaseContext;
import com.jiangli.entity.SysOperationLog;
import com.jiangli.service.SysOperationLogService;
import com.jiangli.vo.EmployeeLoginVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Aspect
@Component
@Slf4j
public class OperationLogAspect {

    @Autowired
    private SysOperationLogService logService;

    // 切点：拦截带@Log注解的admin控制器方法
    @Pointcut("@annotation(com.jiangli.annotation.Log) && within(com.jiangli.controller.admin..*)")
    public void logPointCut() {}

    // 环绕通知：记录核心日志信息
    @Around("logPointCut() && @annotation(log1)")
    public Object around(ProceedingJoinPoint joinPoint, Log log1) throws Throwable {
        SysOperationLog operationLog = new SysOperationLog();
        // 1. 基础信息（无论成功失败都需要）
        operationLog.setOperation(log1.value()); // 操作描述（取自注解）
        operationLog.setCreateTime(LocalDateTime.now()); // 操作时间


            operationLog.setOperatorId(getCurrentOperatorId()); // 操作人员ID}


        // 2. 记录参数（敏感参数可在此处脱敏）
        try {
            Object[] args = joinPoint.getArgs();
            operationLog.setParams(JSON.toJSONString(args)); // 参数转为JSON
        } catch (Exception e) {
            operationLog.setParams("参数解析失败");
        }

        // 3. 执行目标方法并记录结果
        try {
            Object result = joinPoint.proceed();
            if(!log1.value().equals("员工登入"))
            {
                EmployeeLoginVO employeeLoginVO = (EmployeeLoginVO)result;
                operationLog.setOperatorId(employeeLoginVO.getId());
            }// 执行原方法
            operationLog.setErrorMsg(null); // 成功时错误信息为null
            return result;
        } catch (Exception e) {
            operationLog.setErrorMsg(e.getMessage()); // 失败时记录错误信息
            throw e; // 继续抛出异常，不影响原有业务逻辑
        } finally {
            logService.asyncSaveLog(operationLog); // 异步保存日志
        }
    }

    // 获取当前操作人员ID
    private Long getCurrentOperatorId() {
        Long adminId = BaseContext.getCurrentId() == null ? 1L : BaseContext.getCurrentId();
        log.info("操作人员id{}",adminId);
        return adminId;
    }
}
